#pragma once

#include "CoreMinimal.h"
#include "Tetromino.generated.h"

UCLASS()
class UTetromino : public UObject 
{
    GENERATED_BODY()
public:
	UTetromino() = default;

    using FTetrominoShape = TArray<FIntVector>;

	virtual uint32 GetShapeNum() const { return 0; };

	virtual FTetrominoShape GetShape(uint32 Index) const {
		return{};
	};

    uint32 CurrentShapeIndex() const {return Index;}

    void SetCurrentShapeIndex(uint32 Index) {this->Index = Index % GetShapeNum();}
private:
    uint32 Index = 0;
};

UCLASS()
class UTetrominoI : public UTetromino
{
    GENERATED_BODY()
public:
	using FTetrominoShape = UTetromino::FTetrominoShape;
	uint32 GetShapeNum() const override { return ShapeNum; }

	FTetrominoShape GetShape(uint32 Index) const override;
private:
	static constexpr uint32 ShapeNum = 4;
	static const FTetrominoShape Shapes[ShapeNum];
};

UCLASS()
class UTetrominoO : public UTetromino
{
    GENERATED_BODY()
public:
	using FTetrominoShape = UTetromino::FTetrominoShape;
	uint32 GetShapeNum() const override { return ShapeNum; }

	FTetrominoShape GetShape(uint32 Index) const override;
private:
	static constexpr uint32 ShapeNum = 1;
	static const FTetrominoShape Shapes[ShapeNum];
};

UCLASS()
class UTetrominoT : public UTetromino
{
    GENERATED_BODY()
public:
	using FTetrominoShape = UTetromino::FTetrominoShape;
	uint32 GetShapeNum() const override { return ShapeNum; }

	FTetrominoShape GetShape(uint32 Index) const override;
private:
	static constexpr uint32 ShapeNum = 4;
	static const FTetrominoShape Shapes[ShapeNum];
};

UCLASS()
class UTetrominoJ : public UTetromino
{
    GENERATED_BODY()
public:
	using FTetrominoShape = UTetromino::FTetrominoShape;
	uint32 GetShapeNum() const override { return ShapeNum; }

	FTetrominoShape GetShape(uint32 Index) const override;
private:
	static constexpr uint32 ShapeNum = 4;
	static const FTetrominoShape Shapes[ShapeNum];
};

UCLASS()
class UTetrominoL : public UTetromino
{
    GENERATED_BODY()
public:
	using FTetrominoShape = UTetromino::FTetrominoShape;
	uint32 GetShapeNum() const override { return ShapeNum; }

	FTetrominoShape GetShape(uint32 Index) const override;
private:
	static constexpr uint32 ShapeNum = 4;
	static const FTetrominoShape Shapes[ShapeNum];
};

UCLASS()
class UTetrominoS : public UTetromino
{
    GENERATED_BODY()
public:
	using FTetrominoShape = UTetromino::FTetrominoShape;
	uint32 GetShapeNum() const override { return ShapeNum; }

	FTetrominoShape GetShape(uint32 Index) const override;
private:
	static constexpr uint32 ShapeNum = 4;
	static const FTetrominoShape Shapes[ShapeNum];
};

UCLASS()
class UTetrominoZ : public UTetromino
{
    GENERATED_BODY()
public:
	using FTetrominoShape = UTetromino::FTetrominoShape;
	uint32 GetShapeNum() const override { return 4; }

	FTetrominoShape GetShape(uint32 Index) const override;
private:
	static constexpr uint32 ShapeNum = 4;
	static const FTetrominoShape Shapes[ShapeNum];
};